#!/usr/bin/env python

import sys, os, os.path, tarfile, md5
from datetime import datetime

def create_archive():
    """
    Helper function to create archive files
    returns (filename, filesize, md5hash)
    """
    now = datetime.now()
    filename = settings.NIGHTLY['filename'] % {'project':settings.NIGHTLY['project'].lower(),
        'year': now.strftime("%Y"), 'month': now.strftime("%m"), 'day': now.strftime("%d") }
    full_dirname = os.path.join(settings.MEDIA_ROOT, now.strftime("%Y/%m"))
    # make sure dir exists.
    if not os.path.isdir(full_dirname):
        os.makedirs(full_dirname)
    
    full_filename = os.path.join(full_dirname, filename)
    
    tar = tarfile.open(full_filename, "w:gz")
    
    for root, dirs, files in os.walk(settings.NIGHTLY['staging_dir']):
        # nuke .svn directories.
        if '.svn' in dirs:
            dirs.remove('.svn')
        for f in files:
            full = os.path.join(root, f)
            # pop off the staging dir...
            dir = full.replace(settings.NIGHTLY['staging_dir']+'/', '')
            relative = os.path.join(settings.NIGHTLY['project'], dir, f)
            tarinfo = tar.gettarinfo(full, relative)
            tar.addfile(tarinfo, file(full))
    tar.close()
    
    # get hash.
    f = open(full_filename, 'r')
    hash = md5.new(f.read()).hexdigest()
    filesize = os.path.getsize(full_filename)
    f.close()
    
    return (filename, filesize, hash)

# Ensure we've got pysvn
try:
    import pysvn
except ImportError:
    raise 'Error: pysvn v1.51+ is required. Please install it!'

# Bootstrap Django Environment
BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR)
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from django.conf import settings

from main.models import Snapshot, Log

client = pysvn.Client()

# Does the staging dir. exist?
if not os.path.exists(settings.NIGHTLY['staging_dir']):
    raise 'Error: staging directory (%s) does not exist, or is not writable.' % settings.NIGHTLY['staging_dir']

# Do we have an existing checkout?
if client.info(settings.NIGHTLY['staging_dir']) == None:
    print 'No Checkout found. Creating...'
    client.checkout(settings.NIGHTLY['repository'], settings.NIGHTLY['staging_dir'])
    info = client.info(settings.NIGHTLY['staging_dir'])
    
    revision = info.revision.number

    # make archive
    filename, filesize, filehash = create_archive()
    
    s = Snapshot(filehash=filehash, filesize=filesize, filename=filename, revision=revision)
    s.save()
    # we don't do real log info here, since there's probably a LOT of them.
    Log(snapshot=s, revision=revision, author=settings.NIGHTLY['project'], 
            rdate=datetime.now().strftime('%Y-%m-%d %H:%m:%S'), msg='Nightly Logging Begins').save()
    s.changes = s.log_set.count()
    s.save()
    print 'Checked out r%s' % revision
    print 'Good to go!'
    sys.exit()


# Get previous version
previous = Snapshot.objects.all().order_by('-snapshot_time')[0]

# get log of new entries from previous version
log = client.log(settings.NIGHTLY['repository'],
                    pysvn.Revision(pysvn.opt_revision_kind.head), 
                    pysvn.Revision(pysvn.opt_revision_kind.number, previous.revision)
                )
log.pop() # chuck out last entry - it's the same as out previous.revision

if len(log) == 0:
    # nothin' to do.
    print 'No updates since I last checked on %s' % previous.snapshot_time 
    sys.exit()

# begin update
client.update(settings.NIGHTLY['staging_dir'])

# do archive
filename, filesize, filehash = create_archive()

# work out what our new revision will be
revision = log[0].revision.number

# Save snapshot
s = Snapshot(filehash=filehash, filesize=filesize, filename=filename, revision=revision, changes=len(log))
s.save()

# loop through log entries and update
for l in log:
    Log(snapshot=s, revision=l.revision.number, author=l.author, 
        rdate=datetime.fromtimestamp(l.date), msg=l.message).save()





